package com.struct.graph.game
{
	import com.component.ComponentChildren;
	import com.struct.graph.game.body.BaseBody;
	import com.struct.graph.game.body.BulletBody;
	import com.struct.graph.game.body.PlayerBody;
	import com.struct.graph.game.kit.RedPoint;
	import com.utils.Arrow2;
	import com.utils.Collide;
	import com.utils.Physical;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	public class BattleContainer extends ComponentChildren
	{
		public var players:Array;//士兵数组
		public var bodys:Array;//士兵数组
		public var movement:Array;//运动数组
		private var timer:Timer;//只是一个Timer
		
		private var next_id:uint;//当前士兵下标
		private var current:PlayerBody;//当前士兵对象
		private var arrow:Arrow2;//移动提示箭头
		public var skill:Object;
		private var bullet:BulletBody;
		public var rp:RedPoint;
		public function BattleContainer(width:int, height:int)
		{
			super();
			this.width = width;
			this.height = height;
			timer = new Timer(25);
			timer.addEventListener(TimerEvent.TIMER, timerHandler);
			arrow = new Arrow2();
			addChild(arrow);
			rp = new RedPoint();
			addChild(rp);
			arrow.visible = false;
			bodys = [];
			players = [];
			movement = [];
			next_id = 0;
			skill = 3;
			addEventListener(Event.ADDED_TO_STAGE, stageHandler);
		}
		
		private var _run:Boolean;
		private var up:Boolean;
		private var down:Boolean;
		private var left:Boolean;
		private var right:Boolean;
		private function stageHandler(e:Event):void{
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
		}
		private function keyDownHandler(e:KeyboardEvent):void{
			if(!_run && current.move > 0){
				addEventListener(Event.ENTER_FRAME, enterFrame);
			}
			switch(e.keyCode){
				case 87:{//w 上
					up = true;
					break;
				}
				case 83:{//s 下
					down = true;
					break;
				}
				case 65:{//a 左
					left = true;
					break;
				}
				case 68:{//d 右
					right = true;
					break;
				}
			}
		}
		private function keyUpHandler(e:KeyboardEvent):void{
			if(!up && !down && !left && !right){
				_run = false;
				removeEventListener(Event.ENTER_FRAME, enterFrame);
			}
			switch(e.keyCode){
				case 87:{//w 上
					up = false;
					break;
				}
				case 83:{//s 下
					down = false;
					break;
				}
				case 65:{//a 左
					left = false;
					break;
				}
				case 68:{//d 右
					right = false;
					break;
				}
			}
		}
		private function enterFrame(e:Event):void{
			if(--current.move > 0){
				var tempx:int;
				var tempy:int;
				tempy = current.y;
				tempx = current.x;
				if(up){
					tempy -= 4;
				} else if(down){
					tempy += 4;
				}
				if(left){
					tempx -= 4;
				} else if(right){
					tempx += 4;
				}
				var fx:Boolean, fy:Boolean;
				for(var i:uint = 0; i <  bodys.length; ++i){
					var body:BaseBody = bodys[i];
					if(body == current){
						continue;
					}
					if(!fy && point2Collide(body.x, body.y, body.radius, current.x, tempy, current.radius)){//上下
						fy = true;
					}
					if(!fx && point2Collide(body.x, body.y, body.radius, tempx, current.y, current.radius)){
						fx = true;
					}
					if(fx && fy){
						break;
					}
				}
				if(!fy){
					current.y = tempy;
				}
				if(!fx){
					current.x = tempx;
				}
				arrow.x = current.x;
				arrow.y = current.y;
				rp.start(current.x - 32, current.y - 56);
			} else {
				_run = false;
				removeEventListener(Event.ENTER_FRAME, enterFrame);
			}
		}
		
		private function point2Collide(x1:int, y1:int, r1:int, x2:int, y2:int, r2:int):Boolean{
			var dx:Number = x1 - x2;
			var dy:Number = y1 - y2;
			var dist:Number = Math.sqrt(dx*dx + dy*dy);
			return dist < r1 + r2;
		}
		public function addBody(body:BaseBody):void{
			addChild(body);
			if(body is PlayerBody){
				players.push(body);
			}
			bodys.push(body);
		}
		
		/**
		 * 下一个士兵
		 */
		public function nextSoldier():void{
			if(current){
				current.move = 100;
			}
			current = players[next_id] as PlayerBody;
//			current.selected(true);
			current.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			arrow.x = current.x;
			arrow.y = current.y;
			rp.start(current.x - 32, current.y - 56);
			if(++next_id >= players.length){
				next_id = 0;
			}
		}
		/**
		 * 移除一个士兵
		 */
		public function removeSoldier(s:PlayerBody):void{
			var index:int = players.indexOf(s);
			if(index != -1){
				players.splice(index, 1);
				removeChild(s);
			}
		}
		
		private function mouseDownHandler(e:MouseEvent):void{
			arrow.visible = true;
			arrow.setAngle(current.mouseX, current.mouseY);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
		}
		
		private function mouseMoveHandler(e:MouseEvent):void{
			arrow.setAngle(current.mouseX, current.mouseY);
		}
		
		private function mouseUpHandler(e:MouseEvent):void{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			current.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			current.buttonMode = false;
			arrow.visible = false;
			
			if(arrow.speed > 0.1){//发射成功
				bullet = current.getBullet(skill);
				if(bullet.parent == null){
					addBody(bullet);
				}
				bullet.x = current.x;
				bullet.y = current.y;
				bullet.fire(arrow.angle, arrow.speed + 5);
				movement.push(bullet);
				timer.start();
			}
		}
		
		
		public function execution():Boolean{
			for(var i:uint = 0; i <  movement.length; ){
				var s:BaseBody = movement[i];
//				if (movement.length > 2)trace(movement.length);
				if(s.execution()){
					++i;
					checkSoldier(s);//士兵碰撞检测
					checkWalls(s);//墙壁
				} else {
					movement.splice(i, 1);
				}
			}
			return movement.length > 0;
		}
		
		protected function checkWalls(s:BaseBody):void {
			var c:Collide = s.collide;
			if (s.x + s.radius > stage.stageWidth) {
				s.x = stage.stageWidth - s.radius;
				if (0 < c.angle < Math.PI/2){
					c.angle = Math.PI - c.angle;
				}else{
					c.angle -= 3*Math.PI - c.angle;
				}
			} else if (s.x - s.radius < 0) {
				s.x = s.radius;
				if (Math.PI < c.angle < 3*Math.PI/2){
					c.angle = 3*Math.PI - c.angle;
				}else {
					c.angle = Math.PI - c.angle;
				}
			}
			if (s.y + s.radius > stage.stageHeight) {
				s.y = stage.stageHeight - s.radius;
				if (3*Math.PI/2 < c.angle < 2*Math.PI){
					c.angle = 2*Math.PI - c.angle;
				}else{
					c.angle = 2*Math.PI - c.angle;
				}
			} else if (s.y - s.radius < 0) {
				s.y = s.radius;
				if (3*Math.PI/2 < c.angle < 2*Math.PI){
					c.angle = 2*Math.PI - c.angle;
				}else{
					c.angle = Math.PI/2 + c.angle;
				}
			}
		}
		/**
		 * 士兵碰撞检测
		 */
		public function checkSoldier(s:BaseBody):void{
			var check:BaseBody;//被检测Body
			for each(check in bodys){
				if(s == check){//如果是自己
					continue;
				}
				var dx:Number = check.x - s.x;
				var dy:Number = check.y - s.y;
				var dist:Number = Math.sqrt(dx*dx + dy*dy);
				var isCollide:Boolean = dist < s.radius + check.radius;
				
				var tempBullet:BulletBody;
				if((tempBullet = check as BulletBody)){
					if(bullet2Validator(tempBullet, s, isCollide))continue;
				} else if((tempBullet = s as BulletBody)){
					if(bullet2Validator(tempBullet, check, isCollide))continue;
				}
				if (isCollide) {//相撞了
					s.x -= s.collide.speedx;
					s.y -= s.collide.speedy;
					var lB:BaseBody, rB:BaseBody;
					var mark:int;//1: b1在左侧 ;   2:b2在左侧;	3:垂直
					mark = s.x < check.x ? 1: (check.x < s.x ? 2 : 3);
					switch (mark){
						case 1:{
							lB = s;
							rB = check;
							checkA(lB, rB);// 不垂直情况
							break;
						}
						case 2:{
							lB = check;
							rB = s;
							checkA(lB, rB);// 不垂直情况
							break;
						}
						case 3:{
							if (s.y < check.y){
								lB = s;
								rB = check;
							}else{
								lB = check;
								rB = s;
							}
							checkB(lB, rB);//垂直
							break;
						}
					}
					if(tempBullet){
						var f:Boolean;
						if(bullet == check){
							f = s.validtorCollide2Destroy(check.collide);
							if(f)removeSoldier(s as PlayerBody);
						} else if(bullet == s){
							f = check.validtorCollide2Destroy(s.collide);
							if(f)removeSoldier(check as PlayerBody);
						}
					}
				}
			}
		}
		
		private function bullet2Validator(b:BulletBody, player:BaseBody, isCollide:Boolean):Boolean{
			if(b.player == player){//自己的子弹
				if(isCollide){//碰撞
					return !b.init;
				} else if(!b.init){
					b.init = true;
				}
			}
			return false;
		}
		private function checkA(lB:BaseBody, rB:BaseBody):void{
			var angleLR:Number = Math.abs(Math.atan((rB.y - lB.y) / (rB.x - lB.x))); // 球中心连线和水平方向夹角,绝对
			//分两个园得中心连线的倾角是第一象限还是第四象限
			//分解速度到左半球坐标系
			var vxL:Number = 0,
				vyL:Number = 0,
				vxR:Number = 0,
				vyR:Number = 0;
			var isOne:Boolean = false;
			
			var lc:Collide = lB.collide;
			var rc:Collide = rB.collide;
			if (lB.y < rB.y){//第一象限
				vxL = lc.speed * Math.cos(lc.angle - angleLR);
				vyL = lc.speed * Math.sin(lc.angle - angleLR);
				
				vxR = rc.speed * Math.cos(rc.angle - angleLR);
				vyR = rc.speed * Math.sin(rc.angle - angleLR);
				isOne = true;
			}else{//第四象限 和 x正轴(angleLR = 0)
				vxL = lc.speed * Math.cos(lc.angle + angleLR);
				vyL = lc.speed * Math.sin(lc.angle + angleLR);
				
				vxR = rc.speed * Math.cos(rc.angle + angleLR);
				vyR = rc.speed * Math.sin(rc.angle + angleLR);
			}
			var vxL1:Number = ((lc.quality-rc.quality)*vxL+2*rc.quality*vxR)/(lc.quality+rc.quality);
			var vxR1:Number = ((rc.quality-lc.quality)*vxR+2*lc.quality*vxL)/(lc.quality+rc.quality);
			if (isNaN(vxL1)){
				trace("出现错误值");
			}
			//以上求出在左半球坐标系里, 左球和右球的速度分别是
			//vxl1 vyl 和  vxr1 vyr
			//一下计算, 返回到原笛卡尔坐标系中的速度和角度
			lc.speed = Math.abs(Math.sqrt(vxL1 * vxL1 + vyL * vyL));
			rc.speed = Math.abs(Math.sqrt(vxR1 * vxR1 + vyR * vyR));
			
			var ang:Number = 0;
			if (vxL1 == 0){
				if (vyL > 0)ang = Math.PI / 2;
				if (vyL < 0)ang = Math.PI / -2;
			}else{
				ang = Math.atan2(vyL, vxL1);
				if (ang < 0)ang += 2 * Math.PI;
			}
			ang += isOne ? angleLR : -angleLR;//旋转坐标系到笛卡尔
			lc.angle = ang;
			addMoveArr(lB);
			if (vxR1 == 0){
				if (vyR > 0)ang = Math.PI / 2;
				if (vyR < 0)ang = Math.PI / -2;
			}else{
				ang = Math.atan2(vyR, vxR1);
				if (ang < 0)ang += 2 * Math.PI;
			}
			ang += isOne ? angleLR : -angleLR;//旋转坐标系到笛卡尔
			rc.angle = ang;
			addMoveArr(rB);
		}
		private function addMoveArr(s:BaseBody):void{
			var len:int = movement.length;
			for (var i:int = 0; i < len; i ++){
				if (movement[i] == s)return;
			}
			movement.push(s);
		}//close function
		private function checkB(lB:BaseBody, rB:BaseBody):void{
			var lc:Collide = lB.collide;
			var rc:Collide = rB.collide;
			var vxL:Number = 0;
			var vyL:Number = lc.speed * Math.sin(lc.angle);
			var vxR:Number = 0;
			var vyR:Number = rc.speed * Math.sin(rc.angle);
			var vyL1:Number = ((lc.quality-rc.quality)*vxL+2*rc.quality*vxR)/(lc.quality+rc.quality);
			var vyR1:Number = ((rc.quality-lc.quality)*vxR+2*lc.quality*vxL)/(lc.quality+rc.quality);
			if (vyL1 > 0){
				lc.speed = vyL1;
				lc.angle = Math.PI/2;
			}else{
				lc.speed = -vyL1;
				lc.angle = 3*Math.PI/2;
			}
			if (vyR1 > 0){
				rc.speed = vyR1;
				rc.angle = Math.PI/2;
			}else{
				rc.speed = -vyR1;
				rc.angle = 3*Math.PI/2;
			}
		}//close function
		/**
		 * 刚体碰撞检测
		 */
		public function checkBody(s:BaseBody):Boolean{
			return false;
		}
		/**
		 * 静动可摧毁物体碰撞检测
		 */
		public function checkOther(s:BaseBody):Boolean{
			return false;
		}
		/**
		 * 物体动量换算
		 */
		public function conservationOfMomentum(base1:BaseBody, base2:BaseBody):void{
			var c1:Collide = base1.collide;
			var c2:Collide = base2.collide;
			var c1x:Number = c1.speed * Math.cos(c1.angle /180 * Math.PI);
			var c2x:Number = c2.speed * Math.cos(c2.angle /180 * Math.PI);
			var vx:Number = Physical.ConservationOfMomentum(c1.quality + c2.quality, c1x + c2x);
			
			var speedY:Number = c1.speed * Math.sin(c1.angle / 180 * Math.PI);
			//计算双方的 动量守恒 Physical.ConservationOfMomentum
			//获取出来以后给base1.collide和 base1.collide的碰撞系数赋值
			//			base1.collide方法需要自己写下
			//			赋值完毕后加入到 movement数组里
		}
		private function timerHandler(e:TimerEvent):void{
			if(!execution()){
				timer.stop();
				nextSoldier();
				removeAllBullet();
			}
		}
		
		private function removeAllBullet():void
		{
//			if (contains(bullet))removeChild(bullet);
		}
	}
}